﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CodeGenerationPipeline;
using CodeGenerationPipeline.Contracts;
using System.IO;
using VisualStudioProvider.Configuration;
using VisualStudioProvider;
using AbstraX;
using Microsoft.VisualStudio.TextTemplating;
using AbstraX.Contracts;
using System.Diagnostics;
using Utils;
using Microsoft.Build.Framework;

namespace XmlSchemas
{
    public class XmlSchemasGenerator : BaseGenerator
    {
        public override event WatchProcess OnWatchProcess;
        public override event OnFileGeneratedHandler OnFileGenerated;

        public override string Name
        {
            get
            {
                return "Xml Services Generator";
            }
        }

        public override string Description
        {
            get
            {
                return "";
            }
        }

        public override ICodeGenerationPackage GenerateFrom(Dictionary<string, IElementBuild> builds, DirectoryInfo workspaceDirectory)
        {
            try
            {
                if (!VSConfigProvider.TemplatesReady)
                {
                    EventsService.PostMessage(Message.GeneralMessage, "Waiting for project template indexing.");
                }

                var template = VSConfigProvider.ProjectTemplates[@"\XMLManager\XMLManager"];

                // testing code

                var desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
                var directory = Path.Combine(desktop, @"TestGenerator\XMLManager");
                var directoryInfo = new DirectoryInfo(directory);

                if (directoryInfo.Exists)
                {
                    directoryInfo.ForceDelete();
                    directoryInfo.Create();
                }

                // end - testing code

                var parms = new VSTemplateParameters
                {
                    ProjectName = "CodeGenerationPipelineInterface",
                    FrameworkVersion = "4.0",
                    RegisteredOrganization = "Mind Chemistry Inc.",
                    CopyrightYear = "2012"
                };

                EventsService.PostMessage(Message.GeneralMessage, string.Format("Processing '{0}' project template.", template.Name));

                template.CopyAndProcess(directory, parms);

                var project = new VSProject(Path.Combine(directory, "XMLManager.csproj"));

                var codeFile = new FileInfo(Path.Combine(workspaceDirectory.FullName, "InterfaceDocument.cs"));

                templateEngineHost.GeneratorStack.Push(this);

                templateEngineHost.DebugCallback += (sender, e2) =>
                {
                    Debugger.Break();
                };

                templateEngineHost.AbortBuild += (sender, e2) =>
                {
                    throw new StepAbortionException(e2.LastFile);
                };

                EventsService.PostMessage(Message.GeneralMessage, "Generating code.");

                templateEngineHost.GenerateFile<DocumentClassGenerator>(codeFile, "CodeGenerationPipelineInterface", builds.Values.Where(e => e.IsRootObject).ToList());

                project.AddCompileFile(codeFile.FullName, @"Elements\" + codeFile.Name);

                builds.Values.ToList<IElementBuild>().ForEach(e =>
                {
                    codeFile = new FileInfo(Path.Combine(workspaceDirectory.FullName, e.Element.Name + ".cs"));

                    templateEngineHost.GenerateFile<ElementClassGenerator>(e, codeFile, "CodeGenerationPipelineInterface");

                    project.AddCompileFile(codeFile.FullName, @"Elements\" + codeFile.Name);

                    e.Element.Attributes.SelectMany(a => a.Facets).Where(f => f.FacetType.Name == "RestrictionEnumerationAttribute").ToList().ForEach(f =>
                    {
                        var enumCodeFile = new FileInfo(Path.Combine(workspaceDirectory.FullName, e.Element.Name + "Enum.cs"));

                        templateEngineHost.GenerateFile<EnumGenerator>(enumCodeFile, "CodeGenerationPipelineInterface", f.Arguments.Select(a => a.Value.RemoveQuotes()).ToList<string>());

                        project.AddCompileFile(enumCodeFile.FullName, @"Enumerations\" + enumCodeFile.Name);
                    });

                });

                this.EventSources.Add(project);

                EventsService.PostMessage(Message.RequestingBuild, this.Name);

                project.Verbosity = LoggerVerbosity.Minimal;
                project.Compile();

                EventsService.PostMessage(Message.BuildRequestCompleted, this.Name);

                templateEngineHost.GeneratorStack.Pop();
            }
            catch (StepAbortionException ex)
            {
                this.LastException = ex;
                return null;
            }
            catch (Exception ex)
            {
                this.LastException = ex;
                return null;
            }

            return null;
        }

        public override ICodeGenerationPackage GenerateFromPackage(ICodeGenerationPackage incomingPackage)
        {
            throw new NotImplementedException();
        }

        public override IProgrammingLanguage ProgrammingLanguage
        {
            get 
            {
                return domainHost.AvailableLanguages.Single(l => l.WellKnownLanguage == WellKnownLanguage.CSharp);
            }
        }
    }
}
